{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Fully Convolutional Networks for Semantic Segmentation\n",
    "\n",
    "Run in the docker image found in https://github.com/waspinator/deep-learning-explorer\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/opt/conda/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.\n",
      "  from ._conv import register_converters as _register_converters\n",
      "Using TensorFlow backend.\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "import sys\n",
    "import zipfile\n",
    "import random\n",
    "import math\n",
    "import re\n",
    "import time\n",
    "import numpy as np\n",
    "from PIL import Image\n",
    "import matplotlib\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "sys.path.insert(0, '../libraries')\n",
    "import semantic.coco\n",
    "import semantic.config\n",
    "import semantic.models\n",
    "import semantic.weights\n",
    "import semantic.fcn\n",
    "import semantic.evaluate\n",
    "\n",
    "%matplotlib inline\n",
    "%config IPCompleter.greedy=True\n",
    "\n",
    "HOME_DIR = '/home/keras'\n",
    "ROOT_DATA_DIR = os.path.join(HOME_DIR, \"data\")\n",
    "WEIGHTS_DIR = os.path.join(HOME_DIR, \"data/weights\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Dataset\n",
    "\n",
    "Your data should be in the [COCO style format](http://cocodataset.org/#download).\n",
    "\n",
    "Organize the dataset using the following structure:\n",
    "\n",
    "```\n",
    "DATA_DIR\n",
    "│\n",
    "└───annotations\n",
    "│   │   instances_<subset><year>.json\n",
    "│   \n",
    "└───<subset><year>\n",
    "    │   image021.jpeg\n",
    "    │   image022.jpeg\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "with zipfile.ZipFile(os.path.join(ROOT_DATA_DIR, \"shapes.zip\"), \"r\") as zip_ref:\n",
    "    zip_ref.extractall(ROOT_DATA_DIR)\n",
    "\n",
    "DATA_DIR = os.path.join(ROOT_DATA_DIR, \"shapes\")\n",
    "MODEL_DIR = os.path.join(DATA_DIR, \"logs\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "loading annotations into memory...\n",
      "Done (t=0.07s)\n",
      "creating index...\n",
      "index created!\n",
      "loading annotations into memory...\n",
      "Done (t=0.00s)\n",
      "creating index...\n",
      "index created!\n",
      "loading annotations into memory...\n",
      "Done (t=0.01s)\n",
      "creating index...\n",
      "index created!\n"
     ]
    }
   ],
   "source": [
    "dataset_train = semantic.coco.CocoDataset()\n",
    "dataset_train.load_coco(DATA_DIR, subset=\"shapes_train\", year=\"2018\")\n",
    "dataset_train.prepare()\n",
    "\n",
    "dataset_validate = semantic.coco.CocoDataset()\n",
    "dataset_validate.load_coco(DATA_DIR, subset=\"shapes_validate\", year=\"2018\")\n",
    "dataset_validate.prepare()\n",
    "\n",
    "dataset_test = semantic.coco.CocoDataset()\n",
    "dataset_test.load_coco(DATA_DIR, subset=\"shapes_test\", year=\"2018\")\n",
    "dataset_test.prepare()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Configuration"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Configurations:\n",
      "BATCH_MOMENTUM                 0.9\n",
      "BATCH_SIZE                     32\n",
      "GPU_COUNT                      1\n",
      "IMAGES_PER_GPU                 32\n",
      "IMAGE_MAX_DIM                  320\n",
      "IMAGE_META_SIZE                16\n",
      "IMAGE_MIN_DIM                  800\n",
      "IMAGE_MIN_SCALE                0\n",
      "IMAGE_RESIZE_MODE              square\n",
      "IMAGE_SHAPE                    [320 320   3]\n",
      "LEARNING_MOMENTUM              0.9\n",
      "LR_BASE                        0.0002\n",
      "LR_BASE_BASE                   0.0001\n",
      "LR_POWER                       0.9\n",
      "MEAN_PIXEL                     [123.7 116.8 103.9]\n",
      "NAME                           shapes_fcn\n",
      "NUM_CLASSES                    4\n",
      "STEPS_PER_EPOCH                128\n",
      "TRAIN_BN                       False\n",
      "VALIDATION_STEPS               12\n",
      "WEIGHT_DECAY                   5e-05\n",
      "\n",
      "\n"
     ]
    }
   ],
   "source": [
    "class ShapesFcnConfig(semantic.config.Config):\n",
    "    \"\"\"Configuration for training on the Shapes dataset.\n",
    "    Derives from the base Config class and overrides values specific\n",
    "    to the Shapes dataset.\n",
    "    \"\"\"\n",
    "    NAME = \"shapes_fcn\"\n",
    "\n",
    "    IMAGES_PER_GPU = 32\n",
    "\n",
    "    # Number of classes (including background)\n",
    "    NUM_CLASSES = 1 + 3  # background + square, circle, triangle\n",
    "\n",
    "    IMAGE_MAX_DIM = 320\n",
    "    STEPS_PER_EPOCH = 128\n",
    "    VALIDATION_STEPS = int(STEPS_PER_EPOCH / 10)\n",
    "    BATCH_MOMENTUM = 0.9\n",
    "    LEARNING_MOMENTUM = 0.9\n",
    "    LR_BASE_BASE = 0.0001\n",
    "    LR_POWER = 0.9\n",
    "    WEIGHT_DECAY = 0.0001/2\n",
    "    \n",
    "config = ShapesFcnConfig()\n",
    "config.display()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Load Model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "model = semantic.fcn.FCN(config=config, model_dir=MODEL_DIR)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Load weights"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "FCN_WEIGHTS = os.path.join(WEIGHTS_DIR, \"fcn_resnet50_weights_tf_dim_ordering_tf_kernels.h5\")\n",
    "semantic.weights.transfer_FCN_ResNet50(FCN_WEIGHTS)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "inititalize_weights_with = 'fcn_imagenet'  # imagenet or last\n",
    "\n",
    "if inititalize_weights_with == 'imagenet':\n",
    "    weights_path = semantic.models.resnet50_imagenet_weights_path()\n",
    "elif inititalize_weights_with == 'fcn_imagenet':\n",
    "    weights_path = semantic.models.fcn_resnet50_imagenet_weights_path()\n",
    "else:\n",
    "    weights_path = model.find_last()[1]\n",
    "\n",
    "model.load_weights(weights_path, by_name=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Train head\n",
    "\n",
    "Train using only the final layer"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "epochs=40"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Learning Schedule "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "learning_schedule = semantic.utils.create_learning_rate_schedule(\n",
    "    epochs, config.LR_BASE, config.LR_POWER, mode='step_decay')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Selecting layers to train...\n",
      "classify               (Conv2D)\n",
      "Epoch 1/40\n",
      "128/128 [==============================] - 218s 2s/step - loss: 1.6000 - sparse_accuracy_ignoring_last_label: 0.5588 - val_loss: 1.4619 - val_sparse_accuracy_ignoring_last_label: 0.6522\n",
      "Epoch 2/40\n",
      "128/128 [==============================] - 226s 2s/step - loss: 1.2548 - sparse_accuracy_ignoring_last_label: 0.6881 - val_loss: 1.5016 - val_sparse_accuracy_ignoring_last_label: 0.6636\n",
      "Epoch 3/40\n",
      "128/128 [==============================] - 228s 2s/step - loss: 1.1588 - sparse_accuracy_ignoring_last_label: 0.7171 - val_loss: 1.5760 - val_sparse_accuracy_ignoring_last_label: 0.6588\n",
      "Epoch 4/40\n",
      "128/128 [==============================] - 228s 2s/step - loss: 1.1137 - sparse_accuracy_ignoring_last_label: 0.7292 - val_loss: 1.5733 - val_sparse_accuracy_ignoring_last_label: 0.6596\n",
      "Epoch 5/40\n",
      "128/128 [==============================] - 228s 2s/step - loss: 1.0694 - sparse_accuracy_ignoring_last_label: 0.7419 - val_loss: 1.5986 - val_sparse_accuracy_ignoring_last_label: 0.6646\n",
      "Epoch 6/40\n",
      "128/128 [==============================] - 199s 2s/step - loss: 1.0529 - sparse_accuracy_ignoring_last_label: 0.7465 - val_loss: 1.5652 - val_sparse_accuracy_ignoring_last_label: 0.6712\n",
      "Epoch 7/40\n",
      "128/128 [==============================] - 227s 2s/step - loss: 1.0475 - sparse_accuracy_ignoring_last_label: 0.7463 - val_loss: 1.6047 - val_sparse_accuracy_ignoring_last_label: 0.6567\n",
      "Epoch 8/40\n",
      "128/128 [==============================] - 228s 2s/step - loss: 1.0217 - sparse_accuracy_ignoring_last_label: 0.7529 - val_loss: 1.5710 - val_sparse_accuracy_ignoring_last_label: 0.6693\n",
      "Epoch 9/40\n",
      "128/128 [==============================] - 228s 2s/step - loss: 1.0090 - sparse_accuracy_ignoring_last_label: 0.7561 - val_loss: 1.4771 - val_sparse_accuracy_ignoring_last_label: 0.6868\n",
      "Epoch 10/40\n",
      "128/128 [==============================] - 231s 2s/step - loss: 0.9952 - sparse_accuracy_ignoring_last_label: 0.7607 - val_loss: 1.5432 - val_sparse_accuracy_ignoring_last_label: 0.6820\n",
      "Epoch 11/40\n",
      " 13/128 [==>...........................] - ETA: 38s - loss: 1.0060 - sparse_accuracy_ignoring_last_label: 0.7577"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Process ForkPoolWorker-972:\n",
      "Process ForkPoolWorker-976:\n",
      "Process ForkPoolWorker-974:\n",
      "Process ForkPoolWorker-971:\n",
      "Process ForkPoolWorker-975:\n",
      "Process ForkPoolWorker-969:\n",
      "Process ForkPoolWorker-970:\n",
      "Process ForkPoolWorker-973:\n",
      "Traceback (most recent call last):\n",
      "Traceback (most recent call last):\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/process.py\", line 258, in _bootstrap\n",
      "    self.run()\n",
      "Traceback (most recent call last):\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/process.py\", line 258, in _bootstrap\n",
      "    self.run()\n",
      "Traceback (most recent call last):\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/process.py\", line 93, in run\n",
      "    self._target(*self._args, **self._kwargs)\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/process.py\", line 258, in _bootstrap\n",
      "    self.run()\n",
      "Traceback (most recent call last):\n",
      "Traceback (most recent call last):\n",
      "Traceback (most recent call last):\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/process.py\", line 258, in _bootstrap\n",
      "    self.run()\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/process.py\", line 258, in _bootstrap\n",
      "    self.run()\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/process.py\", line 93, in run\n",
      "    self._target(*self._args, **self._kwargs)\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/process.py\", line 258, in _bootstrap\n",
      "    self.run()\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/process.py\", line 93, in run\n",
      "    self._target(*self._args, **self._kwargs)\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/pool.py\", line 108, in worker\n",
      "    task = get()\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/process.py\", line 93, in run\n",
      "    self._target(*self._args, **self._kwargs)\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/process.py\", line 93, in run\n",
      "    self._target(*self._args, **self._kwargs)\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/queues.py\", line 334, in get\n",
      "    with self._rlock:\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/pool.py\", line 108, in worker\n",
      "    task = get()\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/pool.py\", line 108, in worker\n",
      "    task = get()\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/synchronize.py\", line 96, in __enter__\n",
      "    return self._semlock.__enter__()\n",
      "KeyboardInterrupt\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/queues.py\", line 334, in get\n",
      "    with self._rlock:\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/queues.py\", line 334, in get\n",
      "    with self._rlock:\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/pool.py\", line 108, in worker\n",
      "    task = get()\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/synchronize.py\", line 96, in __enter__\n",
      "    return self._semlock.__enter__()\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/pool.py\", line 108, in worker\n",
      "    task = get()\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/process.py\", line 93, in run\n",
      "    self._target(*self._args, **self._kwargs)\n",
      "KeyboardInterrupt\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/queues.py\", line 334, in get\n",
      "    with self._rlock:\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/synchronize.py\", line 96, in __enter__\n",
      "    return self._semlock.__enter__()\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/pool.py\", line 108, in worker\n",
      "    task = get()\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/queues.py\", line 334, in get\n",
      "    with self._rlock:\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/synchronize.py\", line 96, in __enter__\n",
      "    return self._semlock.__enter__()\n",
      "KeyboardInterrupt\n",
      "KeyboardInterrupt\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/process.py\", line 258, in _bootstrap\n",
      "    self.run()\n",
      "Traceback (most recent call last):\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/synchronize.py\", line 96, in __enter__\n",
      "    return self._semlock.__enter__()\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/process.py\", line 93, in run\n",
      "    self._target(*self._args, **self._kwargs)\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/queues.py\", line 335, in get\n",
      "    res = self._reader.recv_bytes()\n",
      "KeyboardInterrupt\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/connection.py\", line 216, in recv_bytes\n",
      "    buf = self._recv_bytes(maxlength)\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/process.py\", line 258, in _bootstrap\n",
      "    self.run()\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/connection.py\", line 407, in _recv_bytes\n",
      "    buf = self._recv(4)\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/pool.py\", line 108, in worker\n",
      "    task = get()\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/process.py\", line 93, in run\n",
      "    self._target(*self._args, **self._kwargs)\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/connection.py\", line 379, in _recv\n",
      "    chunk = read(handle, remaining)\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/pool.py\", line 108, in worker\n",
      "    task = get()\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/queues.py\", line 334, in get\n",
      "    with self._rlock:\n",
      "KeyboardInterrupt\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/queues.py\", line 334, in get\n",
      "    with self._rlock:\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/synchronize.py\", line 96, in __enter__\n",
      "    return self._semlock.__enter__()\n",
      "  File \"/opt/conda/lib/python3.6/multiprocessing/synchronize.py\", line 96, in __enter__\n",
      "    return self._semlock.__enter__()\n",
      "KeyboardInterrupt\n",
      "KeyboardInterrupt\n"
     ]
    },
    {
     "ename": "KeyboardInterrupt",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mKeyboardInterrupt\u001b[0m                         Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-9-020672443f9e>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      2\u001b[0m             \u001b[0mlearning_schedule\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      3\u001b[0m             \u001b[0mepochs\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m             layers='head')\n\u001b[0m",
      "\u001b[0;32m~/explorer/semantic-segmentation/libraries/semantic/fcn.py\u001b[0m in \u001b[0;36mtrain\u001b[0;34m(self, train_dataset, validation_dataset, learning_schedule, epochs, layers, augmentation)\u001b[0m\n\u001b[1;32m    167\u001b[0m             \u001b[0mmax_queue_size\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m100\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    168\u001b[0m             \u001b[0mworkers\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mmultiprocessing\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcpu_count\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 169\u001b[0;31m             \u001b[0muse_multiprocessing\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    170\u001b[0m         )\n\u001b[1;32m    171\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/src/keras/legacy/interfaces.py\u001b[0m in \u001b[0;36mwrapper\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m     89\u001b[0m                 warnings.warn('Update your `' + object_name +\n\u001b[1;32m     90\u001b[0m                               '` call to the Keras 2 API: ' + signature, stacklevel=2)\n\u001b[0;32m---> 91\u001b[0;31m             \u001b[0;32mreturn\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     92\u001b[0m         \u001b[0mwrapper\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_original_function\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     93\u001b[0m         \u001b[0;32mreturn\u001b[0m \u001b[0mwrapper\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/src/keras/engine/training.py\u001b[0m in \u001b[0;36mfit_generator\u001b[0;34m(self, generator, steps_per_epoch, epochs, verbose, callbacks, validation_data, validation_steps, class_weight, max_queue_size, workers, use_multiprocessing, shuffle, initial_epoch)\u001b[0m\n\u001b[1;32m   2228\u001b[0m                     outs = self.train_on_batch(x, y,\n\u001b[1;32m   2229\u001b[0m                                                \u001b[0msample_weight\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0msample_weight\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2230\u001b[0;31m                                                class_weight=class_weight)\n\u001b[0m\u001b[1;32m   2231\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   2232\u001b[0m                     \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mouts\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlist\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/src/keras/engine/training.py\u001b[0m in \u001b[0;36mtrain_on_batch\u001b[0;34m(self, x, y, sample_weight, class_weight)\u001b[0m\n\u001b[1;32m   1881\u001b[0m             \u001b[0mins\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mx\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0my\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0msample_weights\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1882\u001b[0m         \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_make_train_function\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1883\u001b[0;31m         \u001b[0moutputs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtrain_function\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mins\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1884\u001b[0m         \u001b[0;32mif\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0moutputs\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1885\u001b[0m             \u001b[0;32mreturn\u001b[0m \u001b[0moutputs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/src/keras/backend/tensorflow_backend.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, inputs)\u001b[0m\n\u001b[1;32m   2480\u001b[0m         \u001b[0msession\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mget_session\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   2481\u001b[0m         updated = session.run(fetches=fetches, feed_dict=feed_dict,\n\u001b[0;32m-> 2482\u001b[0;31m                               **self.session_kwargs)\n\u001b[0m\u001b[1;32m   2483\u001b[0m         \u001b[0;32mreturn\u001b[0m \u001b[0mupdated\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0moutputs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   2484\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/opt/conda/lib/python3.6/site-packages/tensorflow/python/client/session.py\u001b[0m in \u001b[0;36mrun\u001b[0;34m(self, fetches, feed_dict, options, run_metadata)\u001b[0m\n\u001b[1;32m    898\u001b[0m     \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    899\u001b[0m       result = self._run(None, fetches, feed_dict, options_ptr,\n\u001b[0;32m--> 900\u001b[0;31m                          run_metadata_ptr)\n\u001b[0m\u001b[1;32m    901\u001b[0m       \u001b[0;32mif\u001b[0m \u001b[0mrun_metadata\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    902\u001b[0m         \u001b[0mproto_data\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtf_session\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mTF_GetBuffer\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrun_metadata_ptr\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/opt/conda/lib/python3.6/site-packages/tensorflow/python/client/session.py\u001b[0m in \u001b[0;36m_run\u001b[0;34m(self, handle, fetches, feed_dict, options, run_metadata)\u001b[0m\n\u001b[1;32m   1133\u001b[0m     \u001b[0;32mif\u001b[0m \u001b[0mfinal_fetches\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0mfinal_targets\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mhandle\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mfeed_dict_tensor\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1134\u001b[0m       results = self._do_run(handle, final_targets, final_fetches,\n\u001b[0;32m-> 1135\u001b[0;31m                              feed_dict_tensor, options, run_metadata)\n\u001b[0m\u001b[1;32m   1136\u001b[0m     \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1137\u001b[0m       \u001b[0mresults\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/opt/conda/lib/python3.6/site-packages/tensorflow/python/client/session.py\u001b[0m in \u001b[0;36m_do_run\u001b[0;34m(self, handle, target_list, fetch_list, feed_dict, options, run_metadata)\u001b[0m\n\u001b[1;32m   1314\u001b[0m     \u001b[0;32mif\u001b[0m \u001b[0mhandle\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1315\u001b[0m       return self._do_call(_run_fn, feeds, fetches, targets, options,\n\u001b[0;32m-> 1316\u001b[0;31m                            run_metadata)\n\u001b[0m\u001b[1;32m   1317\u001b[0m     \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1318\u001b[0m       \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_do_call\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0m_prun_fn\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mhandle\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfeeds\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfetches\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/opt/conda/lib/python3.6/site-packages/tensorflow/python/client/session.py\u001b[0m in \u001b[0;36m_do_call\u001b[0;34m(self, fn, *args)\u001b[0m\n\u001b[1;32m   1320\u001b[0m   \u001b[0;32mdef\u001b[0m \u001b[0m_do_call\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfn\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1321\u001b[0m     \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1322\u001b[0;31m       \u001b[0;32mreturn\u001b[0m \u001b[0mfn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1323\u001b[0m     \u001b[0;32mexcept\u001b[0m \u001b[0merrors\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mOpError\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0me\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1324\u001b[0m       \u001b[0mmessage\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcompat\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mas_text\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0me\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmessage\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/opt/conda/lib/python3.6/site-packages/tensorflow/python/client/session.py\u001b[0m in \u001b[0;36m_run_fn\u001b[0;34m(feed_dict, fetch_list, target_list, options, run_metadata)\u001b[0m\n\u001b[1;32m   1305\u001b[0m       \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_extend_graph\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1306\u001b[0m       return self._call_tf_sessionrun(\n\u001b[0;32m-> 1307\u001b[0;31m           options, feed_dict, fetch_list, target_list, run_metadata)\n\u001b[0m\u001b[1;32m   1308\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1309\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0m_prun_fn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mhandle\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfeed_dict\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfetch_list\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/opt/conda/lib/python3.6/site-packages/tensorflow/python/client/session.py\u001b[0m in \u001b[0;36m_call_tf_sessionrun\u001b[0;34m(self, options, feed_dict, fetch_list, target_list, run_metadata)\u001b[0m\n\u001b[1;32m   1407\u001b[0m       return tf_session.TF_SessionRun_wrapper(\n\u001b[1;32m   1408\u001b[0m           \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_session\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0moptions\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfeed_dict\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfetch_list\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtarget_list\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1409\u001b[0;31m           run_metadata)\n\u001b[0m\u001b[1;32m   1410\u001b[0m     \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1411\u001b[0m       \u001b[0;32mwith\u001b[0m \u001b[0merrors\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mraise_exception_on_not_ok_status\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mstatus\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mKeyboardInterrupt\u001b[0m: "
     ]
    }
   ],
   "source": [
    "model.train(dataset_train, dataset_validate,\n",
    "            learning_schedule,\n",
    "            epochs,\n",
    "            layers='head')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Fine tune\n",
    "\n",
    "Train more slowly than before but using more or all the layers. Starts from the previous epoch. For example if you set the train part to have 4 epochs and you want to fine tune for 2, set the epochs below to 6"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "epochs=50"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Learning Schedule "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "learning_schedule = semantic.utils.create_learning_rate_schedule(\n",
    "    epochs, config.LR_BASE/10, config.LR_POWER, mode='step_decay')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model.train(dataset_train, dataset_validate,\n",
    "            learning_schedule,\n",
    "            epochs,\n",
    "            layers='all')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Predict\n",
    "\n",
    "Predict on a sample image"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x7faf13949b38>"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 576x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "test_image_id = np.random.choice(dataset_test.image_ids, 1)[0]\n",
    "image = Image.open(dataset_test.image_reference(test_image_id))\n",
    "plt.figure(figsize=(8,4))\n",
    "plt.axis('off')\n",
    "plt.imshow(image)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "prediction = model.predict(image)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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N19f3/RPPvkkaNCgQQP1en1qYmLiwIMHDwZa78eOHTuC+/fvP8jf3z+tf//+g3bt2mXoaEqmsrJSO3PmzOju3bsn6/X61IEDBw568803u3Tm+WAE72FqjTngCps2bbpSUlLiHxkZ2ZSXl1cqhBDff/+9jxBC5Obm/mj58uVX8/LySrXa1se2er3etH79+pLevXs3njt3zv/pp5+OefLJJ6O3b99+2XIbk8kkli5d+qPVq1dfiYyMNM6dOzd6+vTpfS5evHjGz89PXLp0yW/atGnx48ePv71169aLV69e9cvJyYlub79NJpMYPXp0vNls1rz99tsXo6OjG3fv3h3yxBNP9OnSpcv5CRMm2HW6YwsCD0Aa3bp1a9bpdOaAgACTZfqlrq5OK4QQM2bMuPnUU0/dtty2uLhY1/L+q1atum757wEDBjRWVlZee+KJJ/o0NzdftqzbajabxZo1a65YFvJ+8cUXy372s58lFBUV+aekpDSsXr26e1hYmPGdd94p8fX1Fenp6fVNTU3XJk+e3K+t/d69e3fwyZMnDWVlZae6devWLIQQgwYNKj969Khh3bp13Qk8ALQjKyurtqPbvPnmm13WrVsXWVpa6l9TU+NjNptFU1OT5sqVK35xcXFNQtxdZ9WyrJ8QQsTGxjYKIURZWZlfSkpKw7lz5wKSk5NrfX1/yOtPfvKTdrd99OjRwKamJk10dHSy9c+bmpo0sbGxDi/7R+ABqILBYGh3ce3PP/88aNasWX1/97vfXV+1atXV8PBw44EDBwzz5s2La2houLdYilarFdbxtiys3dzcrGn5M6vL7S5qZDKZNAaDofnw4cNft7zO39/f4QWRCDwAqfj5+ZmsY2ur/fv3G7p06WJcu3ZtmeVn7777bld7HychIaF++/btYUaj8d4LwRdffNHusfaZmZm11dXVPnV1dZqhQ4fW27vNtnAUDQCpxMTENH711VeBZ8+e9b9+/bpvY2OjTbFPSEior6io8H3llVfCi4qKdH/729+6bdmypbu921+0aNF3t2/f9v31r38de+LEiYCdO3cGL1++PEqIB0f2FuPGjavOzs6umjx5cvxbb73VpaioSHfw4MHAFStWdP/rX/8abu8+WBB4AFJZsmTJja5duxqHDh06qFevXikdjZ4tpk2bVjlv3rzrf/rTn6LS09MHv/fee11ffPHFq/Zu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\n",
      "text/plain": [
       "<Figure size 576x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=(8,4))\n",
    "im = plt.imshow(prediction, interpolation='none')\n",
    "values = np.unique(prediction.ravel())\n",
    "colors = [ im.cmap(im.norm(value)) for value in values]\n",
    "patches = [ matplotlib.patches.Patch(color=colors[i], label=\"{}\".format(dataset_test.class_info[i]['name'])) for i in values ]\n",
    "plt.legend(handles=patches, bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0., fontsize='x-large')\n",
    "plt.axis('off')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Evaluate\n",
    "\n",
    "Get the Mean IoU for each class in the dataset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'square': [0.05946580262446679],\n",
       " 'circle': [0.22259326630711762],\n",
       " 'triangle': [0.15420820403381783]}"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "semantic.evaluate.evaluate(model, dataset_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "semantic.utils.result_to_coco(prediction, dataset_test.class_info, config.IMAGE_MAX_DIM, config.IMAGE_MAX_DIM)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
